package org.example.domain.strategy.service.rule.tree.factory.engine.impl;

import lombok.extern.slf4j.Slf4j;
import org.example.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import org.example.domain.strategy.model.valobj.RuleTreeNodeLineVO;
import org.example.domain.strategy.model.valobj.RuleTreeNodeVO;
import org.example.domain.strategy.model.valobj.RuleTreeVO;
import org.example.domain.strategy.service.rule.tree.ILogicTreeNode;
import org.example.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import org.example.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j

public class DecisionTreeEngine implements IDecisionTreeEngine {

    private final Map<String, ILogicTreeNode> logicTreeNodeGroup;

    private final RuleTreeVO ruleTreeVO;

    public DecisionTreeEngine(Map<String, ILogicTreeNode> logicTreeNodeGroup, RuleTreeVO ruleTreeVO) {
        this.logicTreeNodeGroup = logicTreeNodeGroup;
        this.ruleTreeVO = ruleTreeVO;
    }

    @Override
    public DefaultTreeFactory.StrategyAwardVO process(String userId, Long strategyId, Integer awardId, Date endDateTime) {

        Map<String, RuleTreeNodeVO> treeNodeMap = ruleTreeVO.getTreeNodeMap();
        String nextNode = ruleTreeVO.getTreeRootRuleNode();
        DefaultTreeFactory.StrategyAwardVO strategyAwardVO = null;

        // 获取起始节点「根节点记录了第一个要执行的规则」
        RuleTreeNodeVO ruleTreeNode = treeNodeMap.get(nextNode);
        while (null != nextNode) {
            // 获取决策节点
            ILogicTreeNode logicTreeNode = logicTreeNodeGroup.get(ruleTreeNode.getRuleKey());
            String ruleValue = ruleTreeNode.getRuleValue();

            // 决策节点计算
            DefaultTreeFactory.TreeActionEntity treeActionEntity = logicTreeNode.logic(userId, strategyId, awardId, ruleValue,endDateTime);
            RuleLogicCheckTypeVO ruleLogicCheckType = treeActionEntity.getRuleLogicCheckType();
            strategyAwardVO = treeActionEntity.getStrategyAwardVO();
            log.info("决策树引擎【{}】treeId:{} node:{} code:{}", ruleTreeVO.getTreeName(), ruleTreeVO.getTreeId(), nextNode, ruleLogicCheckType.getCode());


            // 获取下一个节点
            nextNode = next(ruleLogicCheckType.getCode(), ruleTreeNode.getTreeNodeLineVOList());
            ruleTreeNode = treeNodeMap.get(nextNode);
        }

        return strategyAwardVO;

    }

    public String next(String matterValue,List<RuleTreeNodeLineVO> ruleTreeNodeLineList){
        if(null == ruleTreeNodeLineList || ruleTreeNodeLineList.isEmpty()){
            return null;
        }

        for (RuleTreeNodeLineVO ruleTreeNodeLine : ruleTreeNodeLineList) {
            if(decisionLogic(matterValue,ruleTreeNodeLine)){
                return ruleTreeNodeLine.getRuleNodeTo();
            }
        }
        /*
        之前版本的问题核心在于：RuleStockLogic处理过程中，如果扣减库存成功，则直接结束，决策值为TAKE_OVER；如果扣减失败，才走兜底奖品，决策值为ALLOW；
        但是数据库中rule_stock->rule_luck_award这条tree_node_line信息如下：3	tree_lock	rule_stock	rule_luck_award	EQUAL	TAKE_OVER	0000-00-00 00:00:00	2025-01-10 09:56:20
        这种情况下扣减成功会走兜底奖品，而扣减失败会直接返回，反了；
        xfg的处理方式是把数据库中的rule_stock->rule_luck_award这条tree_node_line中的决策值改为了ALLOW;
        我觉得rule_stock->rule_luck_award决策值为TAKE_OVER没啥问题，交给rule_luck_award接管，应该将RuleStockLogic中扣减库存成功和失败所返回的决策之调换；
        如此一来，扣减成功直接放行，扣减失败交给rule_luck_award接管，走兜底奖励；
         */
        return null;
    }

    public boolean decisionLogic(String matterValue, RuleTreeNodeLineVO nodeLine) {
        switch (nodeLine.getRuleLimitType()) {
            case EQUAL:
                return matterValue.equals(nodeLine.getRuleLimitValue().getCode());
            // 以下规则暂时不需要实现
            case GT:
            case LT:
            case GE:
            case LE:
            default:
                return false;
        }
    }

}
